﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ValiVIN.Manufacturer;

namespace ValiVIN
{
    internal static class ManufacturerDecode
    {
        static Dictionary<string, IVINManufacturer> _manufacturers;

        private static Dictionary<string, IVINManufacturer> Manufacturers
        {
            get
            {
                if (_manufacturers == null)
                {
                    GenerateManufacturersList();
                }
                return _manufacturers;
            }
        }

        /// <summary>
        /// Make sure to add new manufacturers here
        /// This is the only method that should change in this class
        /// </summary>
        private static void GenerateManufacturersList()
        {
            _manufacturers = new Dictionary<string, IVINManufacturer>();
            //for each WIM assign the Singleton Instance of the Class implementing the IVINManufacturer
            //example: _manufacturers["1CB"] = GenericManufacturer.Instance;

            _manufacturers["5J1"] = (IVINManufacturer)BigDogMotorcycles.Instance;
            _manufacturers["SCC"] = (IVINManufacturer)Lotus.Instance;
            _manufacturers["JNK"] = (IVINManufacturer)Infiniti.Instance;
            _manufacturers["JNR"] = (IVINManufacturer)Infiniti.Instance;
            _manufacturers["ZHW"] = (IVINManufacturer)Lamborghini.Instance;
            _manufacturers["ZA9"] = (IVINManufacturer)SmallManufacturer.Instance;
            _manufacturers["19U"] = (IVINManufacturer)Acura.Instance;
            _manufacturers["JH4"] = (IVINManufacturer)Acura.Instance;
            _manufacturers["2HN"] = (IVINManufacturer)Acura.Instance;
            _manufacturers["1N4"] = Nissan.Instance; // blah, I think explicit 3chars code will be more accurate than 2chars, and bullet proof 
            _manufacturers["1N6"] = Nissan.Instance;
            _manufacturers["5N1"] = Nissan.Instance;
            _manufacturers["3N1"] = Nissan.Instance;
            _manufacturers["4N2"] = Nissan.Instance;
            _manufacturers["JN1"] = Nissan.Instance;
            _manufacturers["JN3"] = Nissan.Instance;
            _manufacturers["JN6"] = Nissan.Instance;
            _manufacturers["JN8"] = Nissan.Instance;
        }

        internal static bool Decode(VINumber vin)
        {
            if (vin == null || string.IsNullOrEmpty(vin.VIN) || vin.VIN.Length != VINCheck._REQUIRED_LENGTH) 
            { return false; }

            string s2 = vin.VIN.Substring(0, 2);
            string s3 = vin.VIN.Substring(0, 3);

            IVINManufacturer mani = null;

            //check the sub companies (pontiac, mercury, infinity, etc...) before the parent
            if (!Manufacturers.TryGetValue(s3, out mani))
            {
                Manufacturers.TryGetValue(s2, out mani); //parent companies
            }

            ClearManufacturerSpecifics(vin);
            if (mani != null)
            {
                vin.ManufacturerSpecifics = new Dictionary<string, string>();
                mani.Decode(vin);
                return true;
            }

            return false;
        }

        internal static void ClearManufacturerSpecifics(VINumber vin)
        {
            vin.Plant = string.Empty;
            vin.EngineType = string.Empty;
            vin.SerialNumber = string.Empty;
            vin.ManufacturerSpecifics = new Dictionary<string, string>();
        }


        internal static string ManufacturerName(string vin)
        {
            if (string.IsNullOrEmpty(vin) || vin.Length != VINCheck._REQUIRED_LENGTH)
            {
                return string.Empty;
            }
            string s2 = vin.Substring(0, 2);
            string s3 = vin.Substring(0, 3);


            IVINManufacturer mani = null;

            if (Manufacturers.ContainsKey(s3)) //check the sub companies (pontiac, mercury, infinity, etc...) before the parent
            {
                mani = Manufacturers[s3];
            }
            else if (Manufacturers.ContainsKey(s2)) //parent companies
            {
                mani = Manufacturers[s2];
            }

            if (mani != null)
            {
                return mani.ManufacturerName(vin);
            }

            return string.Empty;
        }
    }
}
